/*=========================================================================================================================================

					
					USAGE IN			:		VFS PROJECT, GROUP 31
					
					OPERATION TYPE		:		FILE OPERATION
					
					NAME OF FILE		:		add_file.c
					
					NAME OF OPERATION	:		addfile(P1, P2, P3)
					
												- P1: destination file path (in VFS)
												- P2: file name (may not be same as that of file name on Hard Disk)
												- P3: data file path (in Hard Disk)
					
					FORMALY CALLED AS	:		addfile(dest_dir_name, file_name, data_file_path)
					
					VERSION				:		1.0
					
										
					TODO				:		Define a function that accepts two arguments as mentioned above, and does the following:
												
												VALIDATIONS (APPLYING ERROR CODES):
													- mounted, 
													- source file existance (in VFS),
													- output file existance (in Hard Disk), 
													- output file is a text file
													
												TASK:
													- Search the source file in N-ARY
													- Read the contents of the file (File which is in VFS)
													- List (write) the contents read above into an output file (on Hard disk)
													
					OTHER FUNCTIONS		:		- validateMountState()
					CALLED						- search_nary(file_path)
												- validateFileExistance(out_path)
												- validateTextFile(name)
												- search(bst_root, file_path)


==========================================================================================================================================*/

#include"common_headers.h"
int fileInsertion(char parent_Path[300],char file_Name[100],struct Block *block)//makedir
{
	//DECLARATIONS:
	int collect=0;
    struct FileDescriptor *f_desc1=NULL;
    FILE *fptr=NULL;
    int p,m;
    
    //CHECK IF THE FILE DESCRIPTORS ARE AVAILABLE ( USED FD's  <  MAX FD's )
    if(mainHeader.usedFileDescriptors<mainHeader.maximumFileDescriptor)
    {
    	//TRAVERSE THROUGH THE FREE LIST UNTIL MAX FD's AND INSERT THE FILE DETAILS
        for(m=0; m < mainHeader.maximumFileDescriptor; m++)
        {
            if(freelist[m]==0)
            {
            	//INSERTING DETAILS IN FILE DESCRIPTORS
                mainHeader.usedFileDescriptors++;
                freelist[m]=1;
                f_desc1=&fileDescriptors[m];
                strcpy(f_desc1->filename,file_Name);
                strcpy(f_desc1->filetype,"file");	//used to denote that the filetype is file or dir
                f_desc1->filesize=strlen(block->block);
                strcpy(f_desc1->locationpath,parent_Path);
                break;
            }
        }
        
        fptr=fopen(mainHeader.filelabel,"rb+");
    
		if(fptr!=NULL)
		{
			//SEEKING THE POSITION OF THE FILE POINTER TILL THE END, AND THEN WRITING THE BLOCK
			rewind(fptr);
			fseek(fptr,(sizeof(struct MainHeader)+(mainHeader.maximumFileDescriptor*sizeof(char))+(mainHeader.maximumFileDescriptor*sizeof(struct FileDescriptor))+(m*sizeof(struct Block))),SEEK_SET);
			fwrite(block,sizeof(struct Block),1,fptr);
			fclose(fptr);  
			
			//INSERTING INTO DATA STRUCTURES
			ht_start= hash_insert(ht_start, file_Name);
			insert_nary(f_desc1);
			BSTInsert(f_desc1);  
			collect=1;   
		}
		else
		{
		    mainHeader.usedFileDescriptors--;
		    freelist[m]=0;
		}		
    }
    else
    {
    	//FREE FILE DESCRIPTORS ARE NOT AVAILABLE (or) FILE SYSTEM FULL    
    	return collect;    	
    }
    
    return collect;
}


int addfile31(char dest_dir_path[300],char file_name[300],char data_file_path[300]) 
{
	//DECLARATIONS:
	int is_mounted, is_valid_file_name, is_path_exist_in_nary, is_slash_at_end, is_file_already_exist, collect, i;
    FILE *fptr=NULL;
    struct Block *block= NULL;
    char *dest_dir_path_ptr;
    
    //INITIALIZATION:
    collect=0;
    i=0;
    is_mounted = 0; 
    is_valid_file_name = 0;
    is_path_exist_in_nary = 0;
    is_slash_at_end = 0; 
    is_file_already_exist = 0;
    

	//CHECK IF VFS MOUNTED
	is_mounted = validateMountState();
	if(is_mounted)
    {
    	//CHECK IF FILENAME IS VALID ('/' IS NOT ALLOWED IN FILENAME)
    	is_valid_file_name = validateFileName(file_name);
		if(is_valid_file_name)
		{
			//CHECK IF DESTINATION DIRECTORY PATH EXIST (IN VFS)
			is_path_exist_in_nary = search_nary(dest_dir_path);
			if(is_path_exist_in_nary)
			{
				//CHECK IF DESTINATION DIRECTORY HAS '/' IN THE END (IF NOT, CONCATENATE THE '/' IN THE END TO THE DIRECTORY PATH)
				is_slash_at_end = strcmp(dest_dir_path,"/");
				if(is_slash_at_end)
				{
		   			strcat(dest_dir_path,"/");
	   			}
				strcat(dest_dir_path,file_name);
				
				//CHECK IF THE FILE ALREADY EXISTS IN THAT DIRECTORY
				is_file_already_exist = search_nary(dest_dir_path);
				if(is_file_already_exist != 1)
				{
					//OPEN FILE IN "rb" MODE (READ BINARY MODE ONLY - THIS WOULD ALLOW US TO ADD THE FILES FROM "/usr/include" FOLDER)
					//OPENING THE FILE IN "rb+" MODE WILL NOT LET US ADD THE FILE FROM THAT FOLDER, BECAUSE THE PERMISSIONS ARE NOT GRANTED FOR UPDATING THE DETAILS OF THE FILES FROM THAT FOLDER
					fptr = fopen( data_file_path, "rb" );
					if ( fptr != NULL )
		    		{
		    			block= (struct Block *) malloc(sizeof(struct Block));
						fread( block->block,blocksize,1,fptr);
						strcat(block->block,"\0");
						fclose(fptr);
						
						//CALLING A FUNCTION TO INSERT IN THE DATA STRUCTURES
						collect= fileInsertion(dest_dir_path,file_name,block);
						
						//FILE SUCCESSFULLY ADDED
						if(collect==1) 
						{
							printf("addfile_SUCCESS\n");
						}	
						else
						{
							//FREE FILE DESCRIPTORS ARE NOT AVAILABLE (or) FILE SYSTEM FULL
					        printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_04);
						}					
					}
					else
					{
						//UNABLE TO OPEN SPECIFIED DATAFILE PATH
						printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_08);						
					}
				}
				else
				{
					//FILE ALREADY EXIST
					printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_03);
				}    			
			}
			else
			{
				//DIRECTORY DOES NOT EXIST (UNABLE TO CREATE NEW FILE)
				printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_01);
			}		  	 
		}
		else
		{
			//INVALID CHARACTER IN FILENAME
			printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_02);
		}		
    }
    else
    {
    	//VFS NOT MOUNTED
    	printf("addfile_FAILURE %s\n",ERR_VFS_ADDFILE_09);
    }  
    
    return collect;
}

